package cn.tedu.admin.mall.service.impl;

import cn.tedu.admin.mall.dao.persist.mapper.CategoryMapper;
import cn.tedu.admin.mall.dao.persist.repository.CategoryRepository;
import cn.tedu.admin.mall.pojo.bo.CategoryBO;
import cn.tedu.admin.mall.pojo.param.CategoryAddParam;
import cn.tedu.admin.mall.pojo.po.CategoryPO;
import cn.tedu.admin.mall.service.CategoryService;
import cn.tedu.admin.mall.util.CommonUtils;
import cn.tedu.tmall.common.enumerator.ServiceCode;
import cn.tedu.tmall.common.ex.ServiceException;
import cn.tedu.tmall.common.vo.PageData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    private CommonUtils commonUtils;

    @Override
    public PageData<CategoryBO> listCategory(Integer pageNum,Integer pageSize) {
        //从Repository查询数据,Service并不关心Repository
        // 是怎么实现的
        //categoryMapper.list();
        PageData<CategoryPO> pageData = categoryRepository.list(pageNum, pageSize);
        //如果service层依赖的数据层的pageHelper的PageInfo,会有可能传递到controller
        //从PO转换为BO
        PageData<CategoryBO> result = getCategoryBOPageData(pageData);
        return result;
    }

    /**
     * 把PageData-list数据PO 转换为 BO
     * @param pageData
     * @return
     */
    private PageData<CategoryBO> getCategoryBOPageData(PageData<CategoryPO> pageData) {
        PageData<CategoryBO> result = new PageData<>();
        List<CategoryPO> list = pageData.getList();
        List<CategoryBO> categoryBOList = new ArrayList<>();
        for (CategoryPO categoryPO : list) {
            CategoryBO categoryBO = new CategoryBO();
            BeanUtils.copyProperties(categoryPO,categoryBO);
            categoryBOList.add(categoryBO);
        }
        BeanUtils.copyProperties(pageData,result);
        result.setList(categoryBOList);
        return result;
    }

    @Override
    public void addCategory(CategoryAddParam categoryAddParam) {
        log.debug("开始处理增加类别,参数:{}", categoryAddParam);
        //1 类别名称必须唯一
        String name = categoryAddParam.getName();
        //去数据库查一下,通过类别名称这个类别名称
        Integer count = categoryRepository.countByName(name);
        log.debug("根据列表名称{}统计数量,结果:{}",name,count);
        if (count > 0) {
            //存在 抛出异常
            String message = "插入失败,这个类别已经存在";
            log.error(message);
            //todo 出了异常,为了方便前端开发人员处理,我们要统一出参(正常和异常),需要一个状态码
            throw new ServiceException(ServiceCode.ERROR_CONFLICT,message);
        }

        //业务需求 计算深度, 计算它是几级类别
        //1 先看我们要插入了类别是父类还是子类
        //2 如果是父类深度为1,如果是子类,就把父类的深度取出来+1 ,得到的值就是子类的深度
        Long parentId = categoryAddParam.getParentId();
        Long depth = 1L;
        CategoryPO parentCategory = null;
        if (parentId != 0) {
            //我们要插入的子类,判断父类是否存在
            parentCategory = categoryRepository.getCategoryById(parentId);
            if (parentCategory == null) {
                //父类不存在
                String message = "插入失败,父类别不存在";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERROR_CONFLICT,message);
            } else {
                depth = parentCategory.getDepth() + 1;
            }
        }

        CategoryPO category = new CategoryPO();
        BeanUtils.copyProperties(categoryAddParam, category);
        category.setDepth(depth);
        //todo 设置子类isParent状态
        category.setIsParent(0);
        // 第一个写操作
        int rows = categoryRepository.addNew(category);
        if (rows != 1) {
            String message = "添加类别失败，请稍后再尝试！";
            log.warn(message);
            throw new RuntimeException(message);
        }
        //故意报一个异常
        //调用一个别的类的方法,这个方法抛出了异常
        //"".substring(10000);

        //设置父类isParent状态
        // 1.如果是父类isParent不变,如果是子类,把它的父类isParent设置为1

//        if(parentId != 0){ //如果再插入当前父类的子类,还会走这遍逻辑,又更新了一遍,多操作了一次数据库
        if(parentId != 0 && parentCategory.getIsParent()==0){
            //parentId不等于0 肯定就是父类
            CategoryPO updateParentCategory = new CategoryPO();
            updateParentCategory.setId(parentId);
            updateParentCategory.setIsParent(1);
            // 第二个写操作
            rows = categoryRepository.updateById(updateParentCategory);
            if (rows != 1){
                String message = "添加类别失败";
                log.error(message);
                throw new RuntimeException(message);
            }
        }

        //todo 事务处理
        // 全部成功,全部失败
        // ACID 怎么实现的?
        // mysql 的事务是怎么实现的? undo redo 日志
        // jdbc

        // 1.setAutoCommit(false);
        // try{
        //   Create 创建分类 记录下创建之前的状态,记录创建后的状态
        //   Update 更新他的父类的isParent = 1 记录下更新之前的状态,记录更新后的状态
        //   connection.commit();
        // }catch(e){
        //   connection.rollback();
        // }

        //如果我们新增的类别是子类,在插入子类的同时,要把它的父类的is_parent 设置为 1 ;



        // 是否在数据库存在这个类别名称?
        //   存在 抛出异常
        //   不存在 插入数据
        //2 判断下这个新插入的类别是子类别还是父类别
        //   是子类别
        //   看他的父类别是谁?
        //      父类别是否存在
        //          存在 插入
        //          不存在 抛异常
        //    是父类别
        //      直接插入
        // id name p_id is_p    深度   2
        // 1 家电    0   1       一级
        // 2 电视    1   1       二级
        // 3 冰箱    1   1       二级
        // 4 4k电视  2   0       三级
        // 5 双门冰箱 3   1       三级
        // 6 海尔兄弟 5   0       四级
        // 我只查询 子类  电视和冰箱  parent_id != 0
        // 我只查询 子类  4k电视   parent_id != 2
        // 我只查询  最下面那层  parent_id > 1  --> is_parent = 0
        // 我只查询  某一级别   增加级别
    }

}
